# system/main.py
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.responses import JSONResponse
from core.asr_engine import asr_engine
import logging
import time
import os
from typing import Any
from contextlib import asynccontextmanager
from api.v1.router import api_v1_router
from models.db import init_db
from core.config import settings
from core.middleware import log_request, add_process_time_header

# 配置日志
logging.basicConfig(
    level=getattr(logging, settings.LOG_LEVEL.upper()),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(settings.LOG_FILE, encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# 生命周期管理
@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时执行
    logger.info("正在初始化数据库...")
    init_db()
    logger.info("正在加载 ASR 引擎模型...")
    try:
        asr_engine.load_model()  # 调用 load_model()
        if asr_engine.is_ready():
            logger.info("ASR 引擎已就绪")
        else:
            logger.error("ASR 引擎加载完成但未就绪")
    except Exception as e:
        logger.error(f" ASR 引擎加载失败: {e}", exc_info=True)
        raise  # 阻止服务启动，避免后续调用失败

    # 调试代码
    print("\n" + "=" * 60)
    print("已注册的 API 路由:")
    for route in app.routes:
        if hasattr(route, "path"):
            methods = ", ".join(getattr(route, "methods", [])) if hasattr(route, "methods") else "UNKNOWN"
            print(f"{methods:12} {route.path}")
    print("=" * 60 + "\n")

    logger.info("应用启动完成")
    logger.info(f"访问地址: http://{settings.HOST}:{settings.PORT}")
    
    yield  # 应用运行期间
    
    # 关闭时执行
    logger.info("应用正在关闭")

# 创建应用
app = FastAPI(
    title=settings.API_TITLE,
    description=settings.API_DESCRIPTION,
    version=settings.API_VERSION,
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json",
    lifespan=lifespan
)

# 中间件
app.middleware("http")(log_request)
app.middleware("http")(add_process_time_header)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 包含路由
app.include_router(api_v1_router, prefix="/api/v1")

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    logger.warning(f"请求验证失败: {exc}")

    # 安全处理 body，避免包含 UploadFile 导致 JSON 序列化失败
    try:
        body = exc.body
        if isinstance(body, dict):
            # 只保留可序列化的字段，文件字段替换为占位符
            safe_body = {}
            for key, value in body.items():
                if hasattr(value, 'filename'):  # 判断是否是 UploadFile
                    safe_body[key] = f"<file uploaded: {getattr(value, 'filename', 'unknown')}>"
                else:
                    safe_body[key] = value
            body = safe_body
        elif isinstance(body, list):
            # 如果是列表，也做类似处理
            safe_list = []
            for item in body:
                if hasattr(item, 'filename'):
                    safe_list.append(f"<file uploaded>")
                else:
                    safe_list.append(item)
            body = safe_list
        else:
            body = str(type(body))  # 兜底转字符串
    except Exception:
        body = "<invalid body data>"

    return JSONResponse(
        status_code=422,
        content={
            "detail": exc.errors(),
            "body": body  # 现在是安全的
        }
    )
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
    logger.warning(f"HTTP 错误 {exc.status_code}: {exc.detail}")
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail}
    )


@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception):
    logger.error(f"未处理异常: {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={"detail": "服务器内部错误"}
    )


# 根路径
@app.get("/")
def read_root():
    return {
        "message": "Speech Translation API",
        "version": settings.API_VERSION,
        "docs": "/docs",
        "health": "/api/v1/health"
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=settings.DEBUG,
        workers=1,
        log_level=settings.LOG_LEVEL.lower()
    )